#pragma once

#ifndef EVENT_CONTROLLER
#define EVENT_CONTROLLER

#include <map>
#include <set>
#include <algorithm>
#include "EventRegistrator.h"
#include "EventArgs.h"
#include "Utils.h"

namespace cevent {

class EventListener;
class EventController
{
public:
	static EventController& GetInst() {
		return eventController;
	}

	// sender - object, that generate event. Can be NULL.
	// e - no need to delete EventArgs*. GenerateEvent take care of them. Can be NULL or you can leave it empty.
	template<typename E, typename S>
	void GenerateEvent(S* sender, EventArgs* e = nullptr) {
		isGenEvent = true;
		GenerateEvent(sender, e, GetRegistrator<E>()->eventsChain);
		DELETE(e);
		isGenEvent = false;
	}
private:
	friend class EventListener;
	static EventController eventController;
	EventController();
	EventController(const EventController&); // undef
	void operator=(const EventController&); // undef
	virtual ~EventController();

	template <typename T>
	EventRegistrator* GetRegistrator() {
		static EventRegistrator eventRegistrator(++EventRegistrator::ID_NEXT);
		return &eventRegistrator;
	}
	template <typename T>
	void RegisterEventListener(T* t) {
		EventRegistrator* eventRegistrator = GetRegistrator<T>();
		t->eventRegistrator = eventRegistrator;
		eventRegistrator->eventsChain.push_back(new EventListenerWrap(static_cast<EventListener*>(t)));
	};

	void UnRegisterEventListener(EventListener* event);
	void GenerateEvent(void* sender, EventArgs* e, std::list<EventListenerWrap*>& eventQueue);

	bool isGenEvent = false;
};

}

#endif // EVENT_CONTROLLER